home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / Sample Code / Snippets / Toolbox / DateThing / DateThing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-05  |  20.2 KB  |  550 lines  |  [TEXT/MPS ]

  1. /* Simple.c */
  2. /* The simplest C System 7 shell application */
  3. /* This shell can be very handy for debugging and testing things */
  4. /* Add menu items, add dialogs, add controls, or whatever else you need */
  5. /* This sample contains basic application startup and event loop handling, */
  6. /* add more features as your needs increase. */
  7. /* This sample is High Level Event aware, so you can send and receive AppleEvents */
  8. /* from this application */
  9. /* Written  by C.K. Haun <TR> */
  10. /* Apple Developer Tech Support */
  11. /* October 1991, Tokyo, Japan */
  12. /* Of course, Copyright 1991, Apple Computer Inc. */
  13.  
  14. #include "DateThing.h"
  15.  
  16.  
  17.  
  18. /* prototypes */
  19.  
  20. void InitalizeApp(void);
  21. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  22. void DrawMain(WindowPtr drawIt);
  23. Boolean DoSelected(long val);
  24. void SizeMain(WindowPtr theWindow,short how);
  25. void InitAEStuff(void);
  26. void DoHighLevel(EventRecord *AERecord);
  27. void DoDaCall(MenuHandle themenu, long theit);
  28. void DoDocumentClick(WindowPtr theWindow,EventRecord *theEvent);
  29.  
  30. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  31. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  32. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  33. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  34.  
  35. void SampleHelpDialog(void);
  36.  
  37. WindowPtr AddNewWindow(short theID);
  38.  
  39. void NilProc(void);
  40. /* one external */
  41. extern void _DataInit();                                    /* this is the C initialization code */
  42.  
  43. /* globals */
  44. Boolean gQuit, gInBackground;
  45. unsigned long gMySleep;
  46. ProcessSerialNumber gOurSN;
  47. short gHelpItem;
  48.  
  49.  
  50. #pragma segment Main
  51. main()
  52. {
  53.     EventRecord myEventRecord;
  54.     WindowPtr twindow;
  55.     short fHit;
  56.     windowCHandle tempWCH;
  57.  
  58.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  59.     InitalizeApp();
  60.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  61.     do {
  62.           WaitNextEvent(everyEvent, &myEventRecord, gMySleep , nil);
  63.     
  64.         switch (myEventRecord.what) {
  65.             case nullEvent:
  66.        
  67.                 /* no nul processing in this sample */
  68.                 break;
  69.             case updateEvt:
  70.             /* always check to see if it's my window */
  71.             /* this may not seem necessary under 7.0, where it's unlikely or impossible for */
  72.             /* a DA to be in your layer, but there are others  */
  73.             /* who can stick themselves into your window list, */
  74.             /* BalloonWriter comes quickly to mind */
  75.                 if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  76.                 tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  77.                 (ProcPtr)((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);}
  78.                 break;
  79.             case mouseDown:
  80.                 /* first see where the hit was */
  81.                 fHit = FindWindow(myEventRecord.where, &twindow);
  82.                 switch (fHit) {
  83.                 Rect limitRect;
  84.                 Str255 tempString;    
  85.                 long back;
  86.                     case inDesk:                            /* if they hit in desk, then the process manager */
  87.                         break;                              /* will switch us out, we don't need to do anything */
  88.                     case inMenuBar:
  89.                         DoSelected(MenuSelect(myEventRecord.where));
  90.                         break;
  91.                         
  92.                     case inSysWindow:
  93.                         /* pass to the system */
  94.                         SystemClick(&myEventRecord, twindow);
  95.                         break;
  96.                     case inContent:
  97.                         /* Handle content and control clicks here */
  98.                 if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {           /* don't do this unless we have a window open, silly */
  99.                             windowCHandle clicker;
  100.                             clicker = (windowCHandle)GetWRefCon(twindow);
  101.                             /* jump to the content function stored for this window */
  102.                             HLock((Handle)clicker);     /* lock it down so things don't get stupid */
  103.                             ((*clicker)->clickMe)(twindow,&myEventRecord);
  104.                             HUnlock((Handle)clicker);       /* all done */
  105.                         }
  106.  
  107.                         break;
  108.                     case inDrag:
  109.                             DragWindow(twindow, myEventRecord.where, &qd.screenBits.bounds);
  110.                         break;
  111.                     case inGrow:
  112.                         /* Call GrowWindow here if you have a grow box */
  113.                      SetPort(twindow);
  114.                         limitRect = qd.screenBits.bounds;
  115.                         limitRect.top = kMinHeight;
  116.                         GetWTitle(twindow, tempString);
  117.                         /* I'm not letting the user shrink the window so */
  118.                         /* small that the title is truncated */
  119.                         limitRect.left = StringWidth(tempString) + 120;
  120.                         back = GrowWindow(twindow,myEventRecord.where, &limitRect);
  121.                         
  122.                         if (back) {
  123.                         if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  124.                         windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  125.                             Rect sizeRect = ((WindowPtr)twindow)->portRect;                            
  126.                             InvalRect(&sizeRect);
  127.                             sizeRect.top = sizeRect.bottom - 16;
  128.                             sizeRect.left = sizeRect.right - 16;
  129.                             EraseRect(&sizeRect);
  130.                             InvalRect(&sizeRect);                            
  131.                             SizeWindow(twindow, back & 0xffff, back >> 16, true);
  132.                             ((*tempWCH)->sizeMe)(twindow,fHit);                            
  133.                         }}
  134.                        
  135.                         InvalRect(&twindow->portRect);
  136.  
  137.                         break;
  138.                     case inGoAway:
  139.                         /* Click in Close box */
  140.                         if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  141.                 if (TrackGoAway(twindow, myEventRecord.where))
  142.                     (ProcPtr)((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
  143.                         }
  144.                         break;
  145.                                         case inZoomIn:
  146.                     case inZoomOut:
  147.                     if (TrackBox(twindow, myEventRecord.where, fHit)) {
  148.                     if(((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  149.                     windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  150.                             SetPort(twindow);                            
  151.                             
  152.                             ZoomWindow(twindow, fHit, true);
  153.                             InvalRect(&twindow->portRect);                        
  154.                         (ProcPtr)((*tempWCH)->sizeMe)(twindow,fHit);
  155.                         }}
  156.     
  157.                         
  158.                 }
  159.             case mouseUp:
  160.                 /* don't care */
  161.                 break;
  162.                 /* same action for key or auto key */
  163.             case keyDown:
  164.             case autoKey:
  165.                 if (myEventRecord.modifiers & cmdKey)
  166.                     DoSelected(MenuKey(myEventRecord.message & charCodeMask));
  167.                 break;
  168.             case keyUp:
  169.                 /* don't care */
  170.                 break;
  171.             case diskEvt:
  172.                 /* I don't do anything special for disk events, this just passes them */
  173.                 /* to a function that checks for an error on the mount */
  174.                 DoDiskEvents(myEventRecord.message);
  175.                 break;
  176.             case activateEvt:
  177.                 if (myEventRecord.modifiers & activeFlag && ((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow){
  178.                 tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  179.                 (ProcPtr)((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  180.                     }
  181.                 break;
  182.             case networkEvt:
  183.                 /* don't care */
  184.                 break;
  185.             case driverEvt:
  186.                 /* don't care */
  187.                 break;
  188.             case app4Evt:
  189.                 switch ((myEventRecord.message >> 24) & 0x0FF) {     /* high byte of message */
  190.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  191.                         gInBackground = (myEventRecord.message & kResumeMask) == 0;
  192.                         if(!gInBackground){
  193.                         
  194.                         }
  195.                         break;
  196.                 }
  197.                 break;
  198.             default:
  199.                 break;
  200.                 /* This dispatches high level events (AppleEvents, for example) */
  201.                 /* to our dispatch routine.  This is NEW in the event loop for */
  202.                 /* System 7 */
  203.             case kHighLevelEvent:
  204.                 DoHighLevel(&myEventRecord);
  205.                 break;
  206.                 
  207.         }
  208.     }
  209.             while (gQuit != true);
  210.     
  211. }
  212.  
  213. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  214. /* like to perform some action or just know when a DA is opened in your */
  215. /* layer.  Can be handy to track memory problems when a DA is opened */
  216. /* with an Option-open */
  217. void DoDaCall(MenuHandle themenu, long theit)
  218. {
  219.     long qq;
  220.     char DAname[255];
  221.     GetItem(themenu, theit, &DAname);
  222.     qq = OpenDeskAcc(DAname);
  223. }
  224.  
  225. /* end DoDaCall */
  226.  
  227. /* DoDiskEvents just checks the error code from the disk mount, */
  228. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  229. /* You can do much more here if you care about what disks are */
  230. /* in the drive */
  231. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  232. {
  233.     short hival, loval, tommy;
  234.     Point fredpoint =  {
  235.         40, 40
  236.     };
  237.     hival = HiWord(dinfo);
  238.     loval = LoWord(dinfo);
  239.     if (hival != noErr)                                     /* something happened */ {
  240.         tommy = DIBadMount(fredpoint, dinfo);
  241.     }
  242. }
  243.  
  244. /* draws my window.  Pretty simple */
  245. void DrawMain(WindowPtr drawIt)
  246. {
  247.     RgnHandle tempRgn;
  248.     Rect scratchRect;
  249.     BeginUpdate(drawIt);
  250.     SetPort(drawIt);
  251.     scratchRect = drawIt->portRect;
  252.     scratchRect.top = scratchRect.bottom - 15;
  253.     scratchRect.left = scratchRect.right - 15;
  254.     tempRgn = NewRgn();
  255.     GetClip(tempRgn);
  256.     ClipRect(&scratchRect);
  257.     DrawGrowIcon(drawIt);
  258.     SetClip(tempRgn);
  259.     DisposeRgn(tempRgn);
  260.  
  261.     
  262.     EndUpdate(drawIt);
  263. }
  264.  
  265. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  266. /* mught be handy someday */
  267. /* I usually use it in an application to determine if a keystroke was accepted */
  268. /* by a menu or whether it should be passed along to any other key acceptors */
  269. Boolean DoSelected(long val)
  270. {
  271.     short loval, hival;
  272.     Boolean returnVal = false;
  273.     loval = LoWord(val);
  274.     hival = HiWord(val);
  275.     
  276.     switch (hival) {                                        /* switch off the menu number selected */
  277.         case kAppleMenu:                                    /* Apple menu */
  278.             if (loval != 1) {                               /* if this was not About, it's a DA */
  279.                 DoDaCall(GetMHandle(kAppleMenu), loval);
  280.             } else {
  281.                 Alert(kAboutBox, nil);                      /* do about box */
  282.             }
  283.             returnVal = true;
  284.             break;
  285.         case kFileMenu:                                     /* File menu */
  286.             switch (loval) {
  287.                 case kQuitItem:
  288.                     gQuit = true;                           /* only  item */
  289.                     returnVal = true;
  290.                     break;
  291.                 default:
  292.                     break;
  293.             }
  294.             break;
  295.         case kEditMenu:
  296.             /* edit menu junk */
  297.             /* don't care */
  298.             switch(loval){
  299.             default:
  300.             break;}
  301.             break;
  302.         case kToolsMenu:
  303.             /* add all your test stuff here */
  304.             switch(loval){
  305.             case 1:
  306.             {
  307.             extern void DateSetterDialog(void);
  308.             DateSetterDialog();
  309.  
  310.  
  311.             }
  312.             break;
  313.             default:
  314.             break;}
  315.  
  316.             break;
  317.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  318.             /* I only care about this item.  If anything else is returned here, I don't know what */
  319.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  320.             /* Apple reserves the right to add and change things in the Help menu */
  321.             if (loval == gHelpItem)
  322.                 SampleHelpDialog();
  323.             break;
  324.             
  325.     }
  326.     HiliteMenu(0);
  327.     return(returnVal);
  328. }
  329.  
  330.  
  331. void DoDocumentClick(WindowPtr theWindow,EventRecord *theEvent)
  332. {
  333.  
  334. }
  335.  
  336.  
  337. /* InitAEStuff installs my appleevent handlers */
  338. void InitAEStuff(void)
  339. {
  340.     AEinstalls HandlersToInstall[] =  { {
  341.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  342.         },  {
  343.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  344.         },  {
  345.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  346.         },  {
  347.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  348.         }, 
  349.         /* The above are the four required AppleEvents. */
  350.         
  351.     };
  352.     
  353.     OSErr aevtErr = noErr;
  354.     long aLong = 0;
  355.     Boolean gHasAppleEvents = false;
  356.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  357.     *   then we exit */
  358.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  359.     /* The following series of calls installs all our AppleEvent Handlers.
  360.     *   These handlers are added to the application event handler list that 
  361.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  362.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  363.     *   list of handlers and dispatch to it if there is one.
  364.     */
  365.     if (gHasAppleEvents) {
  366.         register qq;
  367.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  368.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  369.                                             HandlersToInstall[qq].theProc, 0, false);
  370.             if (aevtErr) {
  371.                 ExitToShell();                              /* just fail, baby */
  372.             }
  373.         }
  374.     } else {
  375.         ExitToShell();
  376.     }
  377. }
  378.  
  379. /* end InitAEStuff */
  380. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  381. /* easy for me to say, huh? */
  382. void DoHighLevel(EventRecord *AERecord)
  383. {OSErr myErr;
  384.     myErr=AEProcessAppleEvent(AERecord);
  385.     
  386. }
  387.  
  388. /* end DoHighLevel */
  389.  
  390. /* This is the standard Open Application event.  */
  391. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  392. {WindowPtr myWindow; 
  393.  
  394. #pragma unused (messagein,reply,refIn)
  395.     /* we of course don't do anything here in this simple app */
  396.     /* except open our window */
  397.     myWindow = AddNewWindow(kDocWindowResID);
  398.     
  399.     return(noErr);
  400. }
  401.  
  402. /* end AEOpenHandler */
  403.  
  404. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  405. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  406. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  407. /* handler will get called. Which means you don't do any initialization of globals here, or */
  408. /* anything else except open then doc.  */
  409. /* SO-- Do NOT assume that you are at app start time in this */
  410. /* routine, or bad things will surely happen to you. */
  411.  
  412. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  413. {
  414. #pragma unused (messagein,refIn,reply)
  415.     /* we of course don't do anything here */
  416.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  417. }
  418.  
  419. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  420. {                                                           /* no printing handler in yet, so we'll ignore this */
  421.     /* the operation is functionally identical to the ODOC event, with the additon */
  422.     /* of calling your print routine.  */
  423. #pragma unused (messagein,refIn,reply)
  424.     /* we of course don't do anything here */
  425.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  426. }
  427.  
  428. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  429. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  430. /* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
  431. /* come through DTS that calls ExitToShell from quit handlers.  Let me explain... */
  432. /* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
  433. /* 100% in your application world.  A5 is right, you can call any toolbox function, */
  434. /* you can call your own routines, everything _seems_ like you are in complete  */
  435. /* control.  Well, almost but not quite.  The routine has been dispatch to from the */
  436. /* AppleEvent Manager's space, so you _must_ return to that at some point! */
  437. /* Which is why you can't call ETS from here.  When you call ExitToShell from an */
  438. /* AE Handler, the most likely thing that happens is the FInder quits, and your  */
  439. /* application keeps running.  Which ain't what you want, y'know? */
  440. /* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
  441. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  442. {
  443. #pragma unused (messagein,refIn,reply)
  444.     gQuit = true;
  445.     return(noErr);
  446. }
  447.  
  448.  
  449.  
  450. /* This is my sample help dialog.  Does not do anything, expand as you need */
  451. void SampleHelpDialog(void)
  452. {
  453.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  454.     short itemhit = 0;
  455.     while (itemhit != 1) {
  456.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  457.     }
  458.     DisposDialog(tdial);
  459. }
  460.  
  461. #pragma segment Initialize
  462. void InitalizeApp(void)
  463. {
  464.     Handle myMenu;
  465.     MenuHandle helpHandle,appleMenuHandle;
  466.     StringHandle helpString;
  467.     short count;
  468.     long vers;
  469.     MaxApplZone();
  470.     InitGraf((Ptr)&qd.thePort);
  471.     InitFonts();
  472.     InitWindows();
  473.     InitMenus();
  474.     TEInit();
  475.     InitDialogs(nil);
  476.     InitCursor();
  477.     /* Check system version */
  478.     Gestalt(gestaltSystemVersion, &vers);
  479.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  480.     if (vers < 7) {
  481.         StopAlert(kBadSystem, nil);
  482.         ExitToShell();
  483.     }
  484.     InitAEStuff();
  485.     /* set up my menu junk */
  486.     myMenu = GetNewMBar(kMBarID);
  487.     SetMenuBar(myMenu);
  488.     appleMenuHandle = GetMHandle(kAppleMenu);
  489.     AddResMenu(appleMenuHandle, 'DRVR');
  490.  
  491.     /* now install my Help menu item in the Help Manager's menu */
  492.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  493.     count = CountMItems(helpHandle);                        /* How many items are there? */
  494.     helpString = GetString(kHelpString);                    /* get my help string */
  495.     DetachResource(helpString);                             /* detach it */
  496.     HNoPurge(helpString);
  497.     MoveHHi((Handle)helpString);
  498.     HLock((Handle)helpString);
  499.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  500.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  501.     
  502.        
  503.     DrawMenuBar();
  504.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  505.     
  506. }
  507.  
  508.  
  509. #pragma segment Main
  510. WindowPtr AddNewWindow(short theID)
  511. {
  512.     windowCHandle setControls;
  513.     WindowPtr tempWP;
  514.     short cnt = 0;
  515.     Str31 wtitle;
  516.     tempWP = GetNewWindow(theID, 0, (WindowPtr)-1);        /* get a new window */
  517.     ((WindowPeek)tempWP)->windowKind = kMyDocumentWindow;     /* mark it as my document window */
  518.     setControls = (windowCHandle)NewHandleClear(sizeof(windowControl));       /* add our control structure to it */
  519.     SetWRefCon(tempWP,(long)setControls);    /* stop stuffing refCon directly <ckh 1.0.3> */
  520.     HLock((Handle)setControls);                             /* lock it down while we fill it*/
  521.     
  522.     /* add pointers to our procedures for drawing, saving, and closing */
  523.     /* This way, all I need is one dispatch point for drawing, closing */
  524.     /* or whatever, I don't have to case off the window kind to go to the  */
  525.     /* correct routine.  Kinda like object-oriented programming, but I won't */
  526.     /* admit that. */
  527.     (*setControls)->drawMe = DrawMain;
  528.     (*setControls)->clickMe = DoDocumentClick;
  529.     (*setControls)->sizeMe = SizeMain;
  530.     (*setControls)->generalData = NewHandle(0);
  531. return(tempWP);
  532. }
  533.  
  534. void SizeMain(WindowPtr theWindow,short how)
  535. {
  536. WindowPtr tempWP;
  537. GetPort(&tempWP);
  538. InvalRect(&theWindow->portRect);
  539. SetPort(tempWP);
  540. }
  541.  
  542. void NilProc(void)
  543. {
  544.  
  545. }
  546.  
  547.  
  548.  
  549.  
  550.